//
//  SKYDevice.m
//  SkyonSDK
//
//  Created by macbook on 2018/5/6.
//  Copyright © 2018年 Skyon. All rights reserved.
//

#import "SKYDevice.h"
//磁盘容量
#import <sys/mount.h>
//广告标识符
#import <AdSupport/AdSupport.h>
//获取设备型号
#import <sys/utsname.h>
//iOS7以下获取mac地址
#import <sys/sysctl.h>
#import <net/if.h>
#import <net/if_dl.h>
//获取ip
#import <ifaddrs.h>
#import <arpa/inet.h>
//cpu占有率
#import <mach/mach.h>
//wifi信息
#import <NetworkExtension/NetworkExtension.h>
#import <SystemConfiguration/CaptiveNetwork.h>
//检查陀螺仪
#import <CoreMotion/CoreMotion.h>
//NFC
#import <CoreNFC/CoreNFC.h>
//cpu 架构
#import <mach-o/arch.h>
//iOS7操作keychain
#import "SKYSSKeychain.h"
#import "SKYInfoServer.h"

NSString *const kSKYDeviceKeychainService = @"SKYIdentifierForVendor";
NSString *const kSKYDeviceKeychainAccount = @"SKYUUID";
@implementation SKYDevice

// 共享实例
SKY_DEF_SINGLETON(SKYDevice)

// 设备名称
+ (NSString *)getDeviceName {
    NSString* deviceName = [[UIDevice currentDevice] name];
    return deviceName;
}

// 设备默认语言
+ (NSString *)getDefaultLanguage {
    NSArray *languageArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"];
    NSString *language = [languageArray objectAtIndex:0];
//    if ([language rangeOfString:@"en"].location != NSNotFound)        return @"英文";
//    if ([language rangeOfString:@"zh-Hans"].location != NSNotFound)   return @"简体中文";
//    if ([language rangeOfString:@"zh-Hant"].location != NSNotFound)   return @"繁体中文";
//    if ([language rangeOfString:@"ja"].location != NSNotFound)        return @"日文";
//    return @"";
    return language;
}

// 设备型号
+ (NSString *)getDeviceModel {
    struct utsname systemInfo;
    uname(&systemInfo);
    NSString *machineString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
    if ([machineString isEqualToString:@"iPhone1,1"])   return @"iPhone 1G";
    if ([machineString isEqualToString:@"iPhone1,2"])   return @"iPhone 3G";
    if ([machineString isEqualToString:@"iPhone2,1"])   return @"iPhone 3GS";
    if ([machineString isEqualToString:@"iPhone3,1"])   return @"iPhone 4";
    if ([machineString isEqualToString:@"iPhone3,3"])   return @"iPhone 4 Verizon";
    if ([machineString isEqualToString:@"iPhone4,1"])   return @"iPhone 4S";
    if ([machineString isEqualToString:@"iPhone5,1"])   return @"iPhone 5 GSM";
    if ([machineString isEqualToString:@"iPhone5,2"])   return @"iPhone 5 CDMA";
    if ([machineString isEqualToString:@"iPhone5,3"])   return @"iPhone 5C GSM";
    if ([machineString isEqualToString:@"iPhone5,4"])   return @"iPhone 5C GSM CDMA";
    if ([machineString isEqualToString:@"iPhone6,1"])   return @"iPhone 5S GSM";
    if ([machineString isEqualToString:@"iPhone6,2"])   return @"iPhone 5S GSM CDMA";
    if ([machineString isEqualToString:@"iPhone7,2"])   return @"iPhone 6";
    if ([machineString isEqualToString:@"iPhone7,1"])   return @"iPhone 6 Plus";
    if ([machineString isEqualToString:@"iPhone8,1"])   return @"iPhone 6S";
    if ([machineString isEqualToString:@"iPhone8,2"])   return @"iPhone 6S Plus";
    if ([machineString isEqualToString:@"iPhone8,4"])   return @"iPhone SE";
    
    // 日行两款手机型号均为日本独占，可能使用索尼FeliCa支付方案而不是苹果支付
    if ([machineString isEqualToString:@"iPhone9,1"])   return @"Chinese iPhone 7";
    if ([machineString isEqualToString:@"iPhone9,2"])   return @"Chinese iPhone 7 Plus";
    if ([machineString isEqualToString:@"iPhone9,3"])   return @"American iPhone 7";
    if ([machineString isEqualToString:@"iPhone9,4"])   return @"American iPhone 7 Plus";
    if ([machineString isEqualToString:@"iPhone10,1"])  return @"Chinese iPhone 8";
    if ([machineString isEqualToString:@"iPhone10,4"])  return @"Global iPhone 8";
    if ([machineString isEqualToString:@"iPhone10,2"])  return @"Chinese iPhone 8 Plus";
    if ([machineString isEqualToString:@"iPhone10,5"])  return @"Global iPhone 8 Plus";
    if ([machineString isEqualToString:@"iPhone10,3"])  return @"Chinese iPhone X";
    if ([machineString isEqualToString:@"iPhone10,6"])  return @"Global iPhone X";
    
    if ([machineString isEqualToString:@"iPod1,1"])     return @"iPod Touch 1G";
    if ([machineString isEqualToString:@"iPod2,1"])     return @"iPod Touch 2G";
    if ([machineString isEqualToString:@"iPod3,1"])     return @"iPod Touch 3G";
    if ([machineString isEqualToString:@"iPod4,1"])     return @"iPod Touch 4G";
    if ([machineString isEqualToString:@"iPod5,1"])     return @"iPod Touch 5Gen";
    if ([machineString isEqualToString:@"iPod7,1"])     return @"iPod Touch 6G";
    
    if ([machineString isEqualToString:@"iPad1,1"])     return @"iPad 1";
    if ([machineString isEqualToString:@"iPad1,2"])     return @"iPad 3G";
    if ([machineString isEqualToString:@"iPad2,1"])     return @"iPad 2 WiFi";
    if ([machineString isEqualToString:@"iPad2,2"])     return @"iPad 2 GSM";
    if ([machineString isEqualToString:@"iPad2,3"])     return @"iPad 2 CDMA";
    if ([machineString isEqualToString:@"iPad2,4"])     return @"iPad 2 CDMA";
    if ([machineString isEqualToString:@"iPad2,5"])     return @"iPad Mini WiFi";
    if ([machineString isEqualToString:@"iPad2,6"])     return @"iPad Mini GSM";
    if ([machineString isEqualToString:@"iPad2,7"])     return @"iPad Mini CDMA";
    if ([machineString isEqualToString:@"iPad3,1"])     return @"iPad 3 WiFi";
    if ([machineString isEqualToString:@"iPad3,2"])     return @"iPad 3 GSM";
    if ([machineString isEqualToString:@"iPad3,3"])     return @"iPad 3 CDMA";
    if ([machineString isEqualToString:@"iPad3,4"])     return @"iPad 4 WiFi";
    if ([machineString isEqualToString:@"iPad3,5"])     return @"iPad 4 GSM";
    if ([machineString isEqualToString:@"iPad3,6"])     return @"iPad 4 CDMA";
    if ([machineString isEqualToString:@"iPad4,1"])     return @"iPad Air";
    if ([machineString isEqualToString:@"iPad4,2"])     return @"iPad Air Cellular";
    if ([machineString isEqualToString:@"iPad4,4"])     return @"iPad Mini 2";
    if ([machineString isEqualToString:@"iPad4,5"])     return @"iPad Mini 2 Cellular";
    if ([machineString isEqualToString:@"iPad4,7"])     return @"iPad Mini 3 WiFi";
    if ([machineString isEqualToString:@"iPad4,8"])     return @"iPad Mini 3 Cellular";
    if ([machineString isEqualToString:@"iPad4,9"])     return @"iPad Mini 3 Cellular";
    if ([machineString isEqualToString:@"iPad5,1"])     return @"iPad Mini 4 WiFi";
    if ([machineString isEqualToString:@"iPad5,2"])     return @"iPad Mini 4 Cellular";
    
    if ([machineString isEqualToString:@"iPad5,3"])     return @"iPad Air 2 WiFi";
    if ([machineString isEqualToString:@"iPad5,4"])     return @"iPad Air 2 Cellular";
    if ([machineString isEqualToString:@"iPad6,3"])     return @"iPad Pro 97inch WiFi";
    if ([machineString isEqualToString:@"iPad6,4"])     return @"iPad Pro 97inch Cellular";
    if ([machineString isEqualToString:@"iPad6,7"])     return @"iPad Pro 129inch WiFi";
    if ([machineString isEqualToString:@"iPad6,8"])     return @"iPad Pro 129inch Cellular";
    
    if ([machineString isEqualToString:@"iPad6,11"])    return @"iPad 5 WiFi";
    if ([machineString isEqualToString:@"iPad6,12"])    return @"iPad 5 Cellular";
    if ([machineString isEqualToString:@"iPad7,1"])     return @"iPad Pro 129inch 2nd gen WiFi";
    if ([machineString isEqualToString:@"iPad7,2"])     return @"iPad Pro 129inch 2nd gen Cellular";
    if ([machineString isEqualToString:@"iPad7,3"])     return @"iPad Pro 105inch WiFi";
    if ([machineString isEqualToString:@"iPad7,4"])     return @"iPad Pro 105inch Cellular";
    
    if ([machineString isEqualToString:@"AppleTV2,1"])  return @"appleTV2";
    if ([machineString isEqualToString:@"AppleTV3,1"])  return @"appleTV3";
    if ([machineString isEqualToString:@"AppleTV3,2"])  return @"appleTV3";
    if ([machineString isEqualToString:@"AppleTV5,3"])  return @"appleTV4";
    
    if ([machineString isEqualToString:@"i386"])        return @"i386Simulator";
    if ([machineString isEqualToString:@"x86_64"])      return @"x86_64Simulator";
    return machineString;
}

// 操作系统平台
+ (NSString *)getSystemName {
    NSString* systemName = [[UIDevice currentDevice] systemName];
    return systemName;
}

// 运营商类型
+ (NSString *)getCarrierName {
    //当前手机所属运营商名称
    NSString *mobile = @"";
#if !TARGET_IPHONE_SIMULATOR
    CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
    CTCarrier *carrier = [info subscriberCellularProvider];
    //先判断有没有SIM卡，如果没有则不获取本机运营商
    if (!carrier.isoCountryCode) {
        mobile = @"无运营商";
    }else{
        mobile = [carrier carrierName];
    }
#endif
    return mobile;
}

// 操作系统版本
+ (NSString *)getSystemVersion {
    NSString* systemVersion = [[UIDevice currentDevice] systemVersion];
    return systemVersion;
}

// 获取内核版本信息
+ (NSString *)getCoreInfo {
    struct utsname systemInfo;
    uname(&systemInfo);
    return [NSString stringWithFormat:@"%@ %@",[NSString stringWithCString:systemInfo.sysname encoding:NSUTF8StringEncoding],[NSString stringWithCString:systemInfo.release encoding:NSUTF8StringEncoding]];
}

// 国际移动用户识别码号码
+ (NSString *)getMCCAndMNC {
    NSString *imsi = @"";
#if !TARGET_IPHONE_SIMULATOR
    CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
    CTCarrier *carrier = [info subscriberCellularProvider];
    NSString *mcc = [carrier mobileCountryCode];
    NSString *mnc = [carrier mobileNetworkCode];
    if(!SKY_IsStrEmpty(mcc) && !SKY_IsStrEmpty(mnc)) {
        imsi = [NSString stringWithFormat:@"%@,%@", mcc, mnc];
    }
#endif
    return imsi;
}

// 分辨率
+ (NSString *)getResolution {
    // 获取屏幕尺寸
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGSize screenSize = screenRect.size;
    // 宽高
    CGFloat scale = [UIScreen mainScreen].scale;
    CGFloat screenX = screenSize.width * scale;
    CGFloat screenY = screenSize.height * scale;
    if(screenX == 1242 && screenY == 2208){ // 资源缩小1.15倍
        screenX = 1080;
        screenY = 1920;
    }
    return [NSString stringWithFormat:@"%0.0f:%0.0f",screenY,screenX];
}

// 已开机时间
+ (NSString *)getElapseBootTime {
    NSTimeInterval time = [[NSProcessInfo processInfo] systemUptime];
//    NSDate* date = [[NSDate alloc] initWithTimeIntervalSinceNow:(0 - time)];
//    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
//    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
//    return [dateFormatter stringFromDate:date];
    return [NSString stringWithFormat:@"%ld",(long)time*1000];
}

// 系统日期和时间
+ (NSString *)getSystemDateTime {
    NSDate* date = [NSDate date];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd,HH:mm:ss"];
    return [dateFormatter stringFromDate:date];
}

// 屏幕尺寸
+ (NSString *)getScreenSize {
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenHeight = screenRect.size.height;
    if(screenHeight == 480){
        return @"3.5";
    }else if(screenHeight == 568){
        return @"4.0";
    }else if(screenHeight == 667){
        return @"4.7";
    }else if(screenHeight == 736){
        return @"5.5";
    }else if(screenHeight == 812){
        return @"5.8";
    }else{
        return @"";
    }
}

// 屏幕密度DPI
+ (NSString *)getDPI {
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGSize screenSize = screenRect.size;
    CGFloat screenX = screenSize.width;
    CGFloat screenY = screenSize.height;
    CGFloat size = [[self getScreenSize] floatValue];
    CGFloat dpi = sqrt(screenX*screenX + screenY*screenY)/size;
    return [NSString stringWithFormat:@"%0.0f",roundf(dpi)];
}

// 屏幕密度PPI
+ (NSString *)getPPI {
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGSize screenSize = screenRect.size;
    CGFloat scale = [UIScreen mainScreen].scale;
    CGFloat screenX = screenSize.width * scale;
    CGFloat screenY = screenSize.height * scale;
    if(screenX == 1242 && screenY == 2208){ // 资源缩小1.15倍
        screenX = 1080;
        screenY = 1920;
    }
    CGFloat size = [[self getScreenSize] floatValue];
    CGFloat ppi = sqrt(screenX*screenX + screenY*screenY)/size;
    return [NSString stringWithFormat:@"%0.0f",roundf(ppi)];
}

- (id)init {
    self = [super init];
    if (self) {
        // GPS
        _manager = [[CLLocationManager alloc] init];
        _manager.delegate = self;
        if([CLLocationManager locationServicesEnabled]){
            _manager.desiredAccuracy = kCLLocationAccuracyBest;
            if ([_manager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
                if (@available(iOS 8.0, *)) {
                    [_manager requestWhenInUseAuthorization];
                    [_manager requestAlwaysAuthorization];
                }
            }
        }
        // 蓝牙
        if (@available(iOS 7.0, *)) {
            NSDictionary *options = @{CBCentralManagerOptionShowPowerAlertKey:@NO};
            _blueManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:options];
        } else {
            _blueManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
        }
    }
    return self;
}

// 是否支持GPS
+ (BOOL)isLocationEnabled {
    return [CLLocationManager locationServicesEnabled];
}

// 开始定位getDiskSize
- (void)startLocation {
    [self.manager stopUpdatingLocation];
    [self.manager startUpdatingLocation];
}

// 开始定位
+ (void)startLocation {
    [[SKYDevice sharedInstance] startLocation];
}

// 停止定位
- (void)stopLocation {
    [self.manager stopUpdatingLocation];
}

// 停止定位
+ (void)stopLocation {
    [[SKYDevice sharedInstance] stopLocation];
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    for (CLLocation *location in locations) {
        CLLocationCoordinate2D locationCoordinate2D = location.coordinate;
        self.latitude = locationCoordinate2D.latitude;
        self.longitude = locationCoordinate2D.longitude;
        self.altitude = location.altitude;
        self.verticalAccuracy = location.verticalAccuracy;
    }
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    if ([error code] == kCLErrorDenied) {
        if ([SKYInfoServer sharedInstance].logEnabled) NSLog(@"访问被拒绝");
    }
    if ([error code] == kCLErrorLocationUnknown) {
        if ([SKYInfoServer sharedInstance].logEnabled) NSLog(@"无法获取位置信息");
    }
}

// 获取经纬度信息
- (NSString *)getLocationInfo {
    return [NSString stringWithFormat:@"%f,%f",self.latitude,self.longitude];
}

// 获取经纬度信息
+ (NSString *)getLocationInfo {
    return [[SKYDevice sharedInstance] getLocationInfo];
}

// 获取海拔高度
- (NSString *)getAltitudeInfo {
    return [NSString stringWithFormat:@"%0.2f",self.altitude];
}

// 获取海拔高度
+ (NSString *)getAltitudeInfo {
    return [[SKYDevice sharedInstance] getAltitudeInfo];
}

// 是否是移动设备
+ (BOOL)isMobile {
    NSString *sModel  = [UIDevice currentDevice].model;
    return [sModel isEqualToString:@"iPhone"];
}

// 获取内存
+ (NSString *)getSystemMemory {
    unsigned long long physicalMemorySize = [[NSProcessInfo processInfo] physicalMemory];
    return sky_formatCapacitySize(physicalMemorySize);
}

// 获取磁盘容量
+ (NSString *)getDiskSize {
    unsigned long long space = 0;
    NSString *sSize = @"";
    // 方法一
    NSError *error = nil;
    NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
    if (!error) {
        space =  [[attrs objectForKey:NSFileSystemSize] unsignedLongLongValue];
        sSize = sky_formatCapacitySize(space);
    }
    // 方法二
//    struct statfs buf;
//    if (statfs("/var", &buf) >= 0) {
//        space = (unsigned long long)(buf.f_bsize * buf.f_blocks);
//        sSize = sky_formatCapacitySize(space);
//    }
    return sSize;
}

// 获取可用磁盘容量
+ (NSString *)getAvailableDiskSize {
    unsigned long long freeSpace = 0;
    NSString *sSize = @"";
    NSError *error = nil;
    NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
    if(!error) {
        freeSpace =  [[attrs objectForKey:NSFileSystemFreeSize] unsignedLongLongValue];
        sSize = sky_formatCapacitySize(freeSpace);
    }
//    struct statfs buf;
//    if (statfs("/var", &buf) >= 0) {
//        freeSpace = (unsigned long long)(buf.f_bsize * buf.f_bavail);
//        sSize = sky_formatCapacitySize(freeSpace);
//    }
    return sSize;
}

// 获取已用磁盘容量
+ (NSString *)getUsedDiskSize {
    unsigned long long space = 0;
    unsigned long long freeSpace = 0;
    NSString *sSize = @"";
    NSError *error = nil;
    NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
    if(!error) {
        space =  [[attrs objectForKey:NSFileSystemSize] unsignedLongLongValue];
        freeSpace =  [[attrs objectForKey:NSFileSystemFreeSize] unsignedLongLongValue];
        sSize = sky_formatCapacitySize(space - freeSpace);
    }
//    struct statfs buf;
//    if (statfs("/var", &buf) >= 0) {
//        usedSpace = (unsigned long long)(buf.f_bsize * (buf.f_blocks - buf.f_bavail));
//        sSize = sky_formatCapacitySize(usedSpace);
//    }
    return sSize;
}

// 获取广告标识符IDFA
+ (NSString *)getIDFA {
    if([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]){
        return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
    }
    return @"";
}

// 是否越狱
+ (BOOL)isJailbroken {
    const char *examineBreak_Tool_pathes[] = {
        "/Applications/Cydia.app",
        "/Library/MobileSubstrate/MobileSubstrate.dylib",
        "/bin/bash",
        "/usr/sbin/sshd",
        "/etc/apt"
    };
    // 判断是否存在越狱文件
    for (int i = 0; i < 5; i++) {
        if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:examineBreak_Tool_pathes[i]]]){
            return YES;
        }
    }
    // 判断是否存在cydia应用
    if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://"]]){
        return YES;
    }
    // 读取系统所有的应用名称
    if ([[NSFileManager defaultManager] fileExistsAtPath:@"/User/Applications/"]){
        return YES;
    }
    // 读取环境变量
    if(getenv("DYLD_INSERT_LIBRARIES")){
        return YES;
    }
    return NO;
}

- (void)centralManagerDidUpdateState:(nonnull CBCentralManager *)central {
    NSString *cbState = @"";
    switch (central.state) {
        case CBManagerStatePoweredOn:
            cbState = @"CBManagerStatePoweredOn";
            break;
        case CBManagerStatePoweredOff:
            cbState = @"CBManagerStatePoweredOff";
            break;
        case CBManagerStateUnsupported:
            cbState = @"CBManagerStateUnsupported";
            break;
        case CBManagerStateResetting:
            cbState = @"CBManagerStateResetting";
            break;
        case CBManagerStateUnauthorized:
            cbState = @"CBManagerStateUnauthorized";
            break;
        default:
            cbState = @"CBManagerStateUnknown";
            break;
    }
    self.supportBlueCentralManager = ![cbState isEqualToString:@"CBManagerStateUnsupported"];
}

// 是否支持蓝牙
+ (BOOL)isBluetoothSupported {
    return [SKYDevice sharedInstance].isSupportBlueCentralManager;
}

+ (NSString *)getBluetoothUUID {
    return @"";
}


/**
 设备唯一标识
 */
+ (NSString *)uniqueDeviceIdentifier;{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
    NSString * uuid = [SKYSSKeychain passwordForService:kSKYDeviceKeychainService account:kSKYDeviceKeychainAccount];
    if (uuid.length > 0) {
        return uuid;
    }
    uuid = [UIDevice currentDevice].identifierForVendor.UUIDString;
    [SKYSSKeychain setPassword:uuid forService:kSKYDeviceKeychainService account:kSKYDeviceKeychainAccount];
    return uuid;
#else
    return [SKYDevice MACAddress];
#endif
}
/**
 1、若通过keychain从service、account中取值不为空，则该值覆盖SDK内部唯一标识
 2、若通过keychain从service、account中取值为空，则设置该值为SDK内部唯一标识
 */
+ (void)keychainPasswordService:(NSString *)service account:(NSString *)account;{
    NSString *appUUID = [SKYSSKeychain passwordForService:service account:account];
    if (appUUID.length > 0) {
        if (![appUUID isEqualToString:[self uniqueDeviceIdentifier]]) {
            [SKYSSKeychain setPassword:appUUID forService:kSKYDeviceKeychainService account:kSKYDeviceKeychainAccount];
        }
        return;
    }
    [SKYSSKeychain setPassword:[self uniqueDeviceIdentifier] forService:service account:account];
}

/**
 iOS7以下获取设备mac地址
 */
+ (NSString *)MACAddress {
    
    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;
    
    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;
    
    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error/n");
        return NULL;
    }
    
    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1/n");
        return NULL;
    }
    
    if ((buf = malloc(len)) == NULL) {
        printf("Could not allocate memory. error!/n");
        return NULL;
    }
    
    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2");
        return NULL;
    }
    
    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    NSLog(@"outString:%@", outstring);
    
    free(buf);
    
    return [outstring uppercaseString];
}
/**
 获取后台进程列表，iOS8以下有效
 */
+ (NSArray *)runningProcesses {
#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_8_0
    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
    size_t miblen = 4;
    size_t size;
    int st = sysctl(mib, (u_int)miblen, NULL, &size, NULL, 0);
    struct kinfo_proc *process = NULL;
    struct kinfo_proc *newprocess = NULL;
    do {
        size += size/10;
        newprocess = realloc(process, size);
        if (!newprocess) {
            if (process) {
                free(process);
            }
            return nil;
        }
        process = newprocess;
        st = sysctl(mib, (u_int)miblen, process, &size, NULL, 0);
    } while (st == -1 && errno == ENOMEM);
    if (st == 0) {
        if (size % sizeof(struct kinfo_proc) == 0) {
            int nprocess = (int)(size/sizeof(struct kinfo_proc));
            if (nprocess) {
                NSMutableArray * array = [[NSMutableArray alloc] init];
                for (int i = nprocess - 1; i >= 0; i--) {
                    NSString *processID = [[NSString alloc] initWithFormat:@"%d", process[i].kp_proc.p_pid];
                    NSString *processName = [[NSString alloc] initWithFormat:@"%s", process[i].kp_proc.p_comm];
                    NSDictionary *dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName, nil]
                                                                       forKeys:[NSArray arrayWithObjects:@"ProcessID", @"ProcessName", nil]];
                    [array addObject:dict];
                }
                free(process);
                return array;
            }
        }
    }
#endif
    return nil;
}

#pragma mark wifi info
// 扫描wifi列表
+ (BOOL)scanWifiList {
    if (@available(iOS 9.0, *)) {
        NSMutableDictionary* options = [[NSMutableDictionary alloc] init];
        [options setObject:@"EFNEHotspotHelperDemo" forKey: kNEHotspotHelperOptionDisplayName];
        dispatch_queue_t queue = dispatch_queue_create("SkyonSDK", NULL);
        return [NEHotspotHelper registerWithOptions: options queue: queue handler: ^(NEHotspotHelperCommand * cmd) {
            NEHotspotNetwork* network;
            if (cmd.commandType == kNEHotspotHelperCommandTypeEvaluate || cmd.commandType == kNEHotspotHelperCommandTypeFilterScanList) {
                // 遍历WiFi列表，获取基本信息
                NSMutableArray* mArray = [NSMutableArray array];
                for (network in cmd.networkList) {
                    //                NSString* wifiInfoString = [[NSString alloc] initWithFormat: @"SSID: %@，Mac地址: %@，信号强度: %f", network.SSID, network.BSSID, network.signalStrength];
                    //                NSLog(@"%@", wifiInfoString);
                    [mArray addObject:network.SSID];
                }
                [SKYDevice sharedInstance].wifiList = mArray;
            }
        }];
    } else {
        return NO;
    }
}

// 获取wifi列表
+ (NSArray *)getWifiList {
    return [[SKYDevice sharedInstance].wifiList copy];
}

/**
 是否连接wifi
 */
+ (BOOL)isConnectWifi {
    return [self wifiMacAddress] == nil ? NO : YES;
}

/**
 wifi mac 地址
 */
+ (NSString *)wifiMacAddress {
    NSDictionary *info = [self networkWifiInfoDict];
    return info != nil ? [info objectForKey:@"BSSID"] : nil;
}

/**
 获取wifi信息
 */
+ (NSDictionary *)networkWifiInfoDict {
    NSArray *ifs = CFBridgingRelease(CNCopySupportedInterfaces());
    id info = nil;
    for (NSString *ifnam in ifs) {
        info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
        if (info && [info count]) {
            break;
        }
    }
    return info;
}

#pragma mark IP info

#define SKY_IOS_CELLULAR    @"pdp_ip0"
#define SKY_IOS_WIFI        @"en0"
#define SKY_IOS_VPN         @"utun0"
#define SKY_IP_ADDR_IPv4    @"ipv4"
#define SKY_IP_ADDR_IPv6    @"ipv6"

#pragma mark - 获取设备当前网络IP地址
+ (NSString *)getLocalIPAddress:(BOOL)preferIPv4 {
    NSArray *searchArray = preferIPv4 ?
    @[ SKY_IOS_VPN @"/" SKY_IP_ADDR_IPv4, SKY_IOS_VPN @"/" SKY_IP_ADDR_IPv6, SKY_IOS_WIFI @"/" SKY_IP_ADDR_IPv4, SKY_IOS_WIFI @"/" SKY_IP_ADDR_IPv6, SKY_IOS_CELLULAR @"/" SKY_IP_ADDR_IPv4, SKY_IOS_CELLULAR @"/" SKY_IP_ADDR_IPv6 ] :
    @[ SKY_IOS_VPN @"/" SKY_IP_ADDR_IPv6, SKY_IOS_VPN @"/" SKY_IP_ADDR_IPv4, SKY_IOS_WIFI @"/" SKY_IP_ADDR_IPv6, SKY_IOS_WIFI @"/" SKY_IP_ADDR_IPv4, SKY_IOS_CELLULAR @"/" SKY_IP_ADDR_IPv6, SKY_IOS_CELLULAR @"/" SKY_IP_ADDR_IPv4 ] ;
    
    NSDictionary *addresses = [self getIPAddresses];
    NSLog(@"addresses: %@", addresses);
    
    __block NSString *address;
    [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
     {
         address = addresses[key];
         //筛选出IP地址格式
         if([self isValidatIP:address]) *stop = YES;
     } ];
    return address ? address : @"0.0.0.0";
}

+ (BOOL)isValidatIP:(NSString *)ipAddress {
    if (ipAddress.length == 0) {
        return NO;
    }
    NSString *urlRegEx = @"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
    
    NSError *error;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:urlRegEx options:0 error:&error];
    
    if (regex != nil) {
        NSTextCheckingResult *firstMatch=[regex firstMatchInString:ipAddress options:0 range:NSMakeRange(0, [ipAddress length])];
        
        if (firstMatch) {
            NSRange resultRange = [firstMatch rangeAtIndex:0];
            NSString *result=[ipAddress substringWithRange:resultRange];
            //输出结果
            NSLog(@"%@",result);
            return YES;
        }
    }
    return NO;
}
+ (NSDictionary *)getIPAddresses {
    NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
    
    // retrieve the current interfaces - returns 0 on success
    struct ifaddrs *interfaces;
    if(!getifaddrs(&interfaces)) {
        // Loop through linked list of interfaces
        struct ifaddrs *interface;
        for(interface=interfaces; interface; interface=interface->ifa_next) {
            if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
                continue; // deeply nested code harder to read
            }
            const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
            char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
            if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
                NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
                NSString *type;
                if(addr->sin_family == AF_INET) {
                    if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
                        type = SKY_IP_ADDR_IPv4;
                    }
                } else {
                    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
                    if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
                        type = SKY_IP_ADDR_IPv6;
                    }
                }
                if(type) {
                    NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
                    addresses[key] = [NSString stringWithUTF8String:addrBuf];
                }
            }
        }
        // Free memory
        freeifaddrs(interfaces);
    }
    return [addresses count] ? addresses : nil;
}
#pragma mark - 是否支持陀螺仪
/**
 是否支持陀螺仪
 */
+ (BOOL)isGyroscopeAvailable {
    CMMotionManager *motionManager = [[CMMotionManager alloc] init];
    BOOL gyroscopeAvailable = motionManager.gyroAvailable;
    return gyroscopeAvailable;
}
#pragma mark - 是否支持NFC
+ (BOOL)isNFCAvailable {
    if (@available(iOS 11.0, *)) {
        return [NFCNDEFReaderSession readingAvailable];
    } else {
        return NO;
    }
}
#pragma mark - CPU
/**
 cpu核心数
 */
+ (NSUInteger)getCPUProcessorCount {
    return [NSProcessInfo processInfo].activeProcessorCount;
}

/**
 cpu占有率
 */
+ (float)getCPUUsage {
    kern_return_t kr;
    mach_msg_type_number_t count;
    static host_cpu_load_info_data_t previous_info = {0, 0, 0, 0};
    host_cpu_load_info_data_t info;
    
    count = HOST_CPU_LOAD_INFO_COUNT;
    
    kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&info, &count);
    if (kr != KERN_SUCCESS) {
        return -1;
    }
    
    natural_t user   = info.cpu_ticks[CPU_STATE_USER] - previous_info.cpu_ticks[CPU_STATE_USER];
    natural_t nice   = info.cpu_ticks[CPU_STATE_NICE] - previous_info.cpu_ticks[CPU_STATE_NICE];
    natural_t system = info.cpu_ticks[CPU_STATE_SYSTEM] - previous_info.cpu_ticks[CPU_STATE_SYSTEM];
    natural_t idle   = info.cpu_ticks[CPU_STATE_IDLE] - previous_info.cpu_ticks[CPU_STATE_IDLE];
    natural_t total  = user + nice + system + idle;
    
    return (user + nice + system) * 100.0 / total;
}
/**
 获取CPU类型（型号）
 */
+ (NSString *)getCPUType {
    host_basic_info_data_t hostInfo;
    mach_msg_type_number_t infoCount;
    
    infoCount = HOST_BASIC_INFO_COUNT;
    host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount);
    
    switch (hostInfo.cpu_type) {
        case CPU_TYPE_ARM:
            return @"CPU_TYPE_ARM";
            break;
            
        case CPU_TYPE_ARM64:
            return @"CPU_TYPE_ARM64";
            break;
            
        case CPU_TYPE_X86:
            return @"CPU_TYPE_X86";
            break;
            
        case CPU_TYPE_X86_64:
            return @"CPU_TYPE_X86_64";
            break;
            
        default:
            return @"";
            break;
    }
}
/**
 cpu架构信息
 */
+ (NSString *)cpuArchitectureDescription {
    return [NSString stringWithUTF8String:NXGetLocalArchInfo()->description];
}


@end
